/*
 * @Author: wuqingchun
 * @Date: 2024-11-29 09:45:09
 * @Description: 可变参数模板
 * @LastEditors: wuqingchun
 * @LastEditTime: 2024-11-29 10:28:49
 */

#include <iostream>

/**
 
 1. typename...位于T之前，表示参数包

 2. T后面的...表示可变参类型，它代表了零到多个不同的类型。T不应被视为单一类型，而是一组类型。
    args通常代表一个参数包或一组参数，这些参数的类型可能各不相同。这个参数包可以包含零到多个任意类型的参数。

 3. sizeof...语法在C++11中引入，用于在可变参数函数模板或类模板内部表示接收到的模板参数个数或类型数量。
 它只适用于可变参数，使用时必须放在圆括号中，可以是函数模板的参数（args）或类型模板参数（T）。

 4. 参数展开
 可变参数函数模板需要处理参数包中的参数展开，通常，参数包的展开是通过递归函数调用来实现的。为此，可变参数函数模板应
 包含一个参数包展开函数和一个对应的递归终止函数，二者共用相同的函数名。
 */
// 显示参数数量和参数类型数量
template <typename... T>
void show_args_count(T... Args)
{
    std::cout << "参数类型数量: " << sizeof...(T) << std::endl;
    std::cout << "参数值数量: " << sizeof...(Args) << std::endl;
}

// 递归终止函数模板
template <typename T, typename... U>
void template_print(T fix_arg)
{
    std::cout << fix_arg << std::endl;
}

template <typename T, typename... U>
void template_print(T fix_arg, U... args)
{
    std::cout << "可变参数个数: " << sizeof... (args) << std::endl;
    std::cout << fix_arg << std::endl;

    // 递归调用
    template_print(args...);
}

int main(int argc, char** argv)
{
    show_args_count(1, "2", '3', 4.0);
    // show_args_count<std::string, int>(1, 2);

    template_print(1, "2", '3', 4.0);
    
    return 0;
}